/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.howtimeflies.simplecrypt;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.List;

/**
 * Created by zhangg on 2015/5/25 0025 16:20.
 *
 * @author <a href=mailto:zhanggeng@howtimeflies.org>GengZhang</a>
 */
public class Decryptor extends Cryptor {

    protected Decryptor(Algorithm algorithm) {
        super(algorithm);
    }

    public boolean decryptFolder(String srcDirPath, String distDirPath,
                                 boolean recursive, FileFilter fileFilter) {
        File srcDir = checkFolder(srcDirPath, true, false, true, false);

        List<File> allFile = FileUtils.listFile(srcDir, recursive, fileFilter);
        int size = allFile.size();
        System.out.println("Find " + size + " matched files");

        File distDir = checkFolder(distDirPath, true, true, false, true);
        System.out.println("==========Start Encrypt========");

        for (int i = 0; i < size; i++) {
            File file = allFile.get(i);
            long start = System.currentTimeMillis();
            String dst = file.getAbsolutePath().replace(srcDirPath, "");
            File distFile = new File(distDir, FileUtils.subExtends(dst, 2));
            distFile.getParentFile().mkdirs();
            try {
                decryptFile(file, distFile);
                long end = System.currentTimeMillis();
                System.out.println("(" + (i + 1) + "/" + size + ") Decrypting " + file.getAbsolutePath() +
                        " to " + distFile.getAbsolutePath() + " Success! " +
                        " File size : " + file.length() / 1024 / 1024d + "m" +
                        " elapsed : " + (end - start) + "ms");
            } catch (Exception e) {
                long end = System.currentTimeMillis();
                System.out.println("(" + (i + 1) + "/" + size + ") Decrypting " + file.getAbsolutePath() +
                        " to " + distFile.getAbsolutePath() + " Failure! " + e.getMessage() +
                        " File size : " + file.length() / 1024 / 1024d + "m" +
                        " elapsed : " + (end - start) + "ms");
            }
        }
        return true;
    }

    public boolean decryptFile(File src, File dist) throws IOException {
        RandomAccessFile inFile = null;
        FileChannel inChannel = null;
        RandomAccessFile outFile = null;
        FileChannel outChannel = null;
        try {
            inFile = new RandomAccessFile(src, "r");
            inChannel = inFile.getChannel();

            outFile = new RandomAccessFile(dist, "rw");
            outChannel = outFile.getChannel();
            int skip = algorithm.decode(inFile);
            inChannel.transferTo(skip, inFile.length() - skip, outChannel);
        } finally {
            closeQuite(outChannel);
            closeQuite(outFile);
            closeQuite(inChannel);
            closeQuite(inFile);
        }

        dist.setLastModified(src.lastModified());
        return true;
    }
}
